/**
 * 所传入的数据中至少应该包含政区中的一个点坐标和政区的范围信息
 */
define([
    'map','animate','threadsQueue','getzqpolymerizationzqData'
], function(map, animate, threadsQueue, getzqData) {
    'use strict';

    let _zqLevelNow = 0;
    let _zqLevelBefore = 0;
    let olmap = map.getMap();
    let mapView = olmap.getView();
    let animateLine = null;

    let isinit = false;
    let isUsing = true;
    let isZooming = false; // 是否是缩放地图，区别于平移

    let _ZoomBefore = 0;
    let _oldPopFeature = null;

    let initCST = {
        showField : "num",
        dataField : "num",
        animateSpeed : 1500,
        popOvelayShowFields : ["name"], // overlay中展示的字段信息
        serverUrl : "./geoLocation",
        scatteringRadius : 30, // 散落至圆周时的圆半径
        PopIconUrl : "../../src/source/images/marker.png",
        zoomMapping : {0: [0, 7], 1: [7, 9] , 2: [9, 12], 3: [12, 13], 4: [13, 18]},
        popHtml : null, // overlay中展示的dom构造函数，返回dom的html以及宽高属性组成的对象
        rgbcall : null, // 要素样式使用的rgb色值，可以根据参数构造色值，返回有边界色值以及中心色值构成的对象
    }

    let currentlabelLayerSource = new ol.source.Vector();
    let currentlabelLayer = null;
    let nextlabelLayerSource = new ol.source.Vector();
    let nextlabelLayer = null;
    let singleLableLayerSource = new ol.source.Vector();
    let singleLableLayer = null;
    let singlePopLableLayerSource = new ol.source.Vector();
    let singlePopLableLayer = null;

    let popupOverlay = null;
    let popHtml = '<div id="popup_ZqPolymerization" class="ol-popup" style="display: none;">' +
                  '    <a href="#" id="popup_ZqPolymerization-closer" class="ol-popup-closer"></a>' +
                  '    <div id="popup_ZqPolymerization-content"></div>' +
                  '</div>';
    let container = null;
    let content = null;
    let popupOverlayCloser = null;


    let getPopHtmlByfeature = null;
    let getRgb = null;
    

    function init(params) {
        if (!isinit) {
            $.extend(initCST, params);
            getRgb = initCST.rgbcall || getRgb;
            getPopHtmlByfeature = initCST.popHtml || getPopHtmlByfeature;
            // 初始化动画插件
            animateLine = new animate({speed: initCST.animateSpeed, StyleFun: getFeatureStyle});
            // 初始化获取政区数据
            getzqData.init({serverUrl: initCST.serverUrl, dataField: initCST.dataField, zoomMapping: initCST.zoomMapping});
            // 初始化UI
            initUi();
            // 初始化图层
            initLayer();
            // 绑定事件
            bindEvent();
            isinit = true;
            // 初始化加载后默认隐藏
            setVisible(false);
        }
    }

    function bindEvent() {
        popupOverlayCloser.onclick = function() {
            popupOverlay.setPosition(undefined);
            popupOverlayCloser.blur();
            return false;
        };
        olmap.on('movestart', movestartEvevt);
        mapView.on('change:resolution', changeviewEvevt);
        olmap.on('moveend', moveendEvevt);
        olmap.on("pointermove", changeCursor);
        olmap.on("click", mapClickEvent);
    }

    /**
     * 地图移动开始时的处理逻辑
     */
    function movestartEvevt() {
        if (isUsing && isZooming) restorePop();
    }

    /**
     * 缩放事件发生时使用两个事件控制动画，
     * changeviewEvevt监听在短时间内是否由有继续缩放的情况，
     * 以控制moveendEvevt触发后setLabels函数是否实行
     */
    function changeviewEvevt() {
        isUsing && (isZooming = true);
    }
    function moveendEvevt() {
        if (isUsing) {
            isZooming = false;
            setTimeout(() => {!isZooming && setLabels()}, 100);
        }
    }

    function changeCursor(e) {
        if (isUsing) {
            let features = getFeatureBypixel(e.pixel);
            let element = olmap.getTargetElement();
            if (features) {
                element.style.cursor = 'pointer';
            } else {
                element.style.cursor = '';
            }
        }
    }

    /**
     * 地图点击事件
     */
    function mapClickEvent(e) {
        let fea = getFeatureBypixel(e.pixel);
        if (!fea) {
            restorePop();
            return;
        };
        let isMark = fea.get("isMark");
        // 显示overlay弹窗信息
        isMark ? (overlayShowPop(fea)) : (notMarkExecute(fea));
    }

    function notMarkExecute(fea) {
        // 按半径扩散至圆周
        if (mapView.getZoom() === mapView.getMaxZoom()) {
            if(_oldPopFeature && fea.get("id") === _oldPopFeature.get("id")){
                return
            }
            threadsQueue.add(dealOutAnimateFeature);
            threadsQueue.add(() => {dealInAnimateFeature(fea)});
            return;
        }
        // 定位相应政区
        let zoomAnimate = getZoomAnimateBycode(fea.get("code"));
        mapView.animate({
            zoom: zoomAnimate,
            center: fea.get("nextlevelcenter"),
            duration: 500,
            easing: function (params) {
                if (params === 1) {
                    isUsing = true;
                }
                return params
            }
        });
    }

    /**
     * 过滤本功能的图层中的图斑
     * @param {Array} pixel 
     * @returns feature
     */
    function getFeatureBypixel(pixel) {
        let features = olmap.getFeaturesAtPixel(pixel, {layerFilter: function (layer){
            return layer.get("c_layerId") === "ZqPolymerization_current_label_Layer" || layer.get("c_layerId") === "ZqPolymerization_singlePopLable_Layer"
        }});
        return features ? features[0] : null;
    }


    function getZoomAnimateBycode(code) {
        let zoomAnimate = undefined;
        switch (code.length) {
            case 2:
                zoomAnimate = initCST.zoomMapping["0"][1];
                break;
            case 4:
                zoomAnimate = initCST.zoomMapping["1"][1];
                break;
            case 6:
                zoomAnimate = initCST.zoomMapping["2"][1];
                break;
            case 9:
                zoomAnimate = initCST.zoomMapping["3"][1];
                break;
            case 12:
                zoomAnimate = initCST.zoomMapping["4"][1];
                break;
        }
        return zoomAnimate;
    }

    /**
     * 关闭弹窗overlay以及按半径聚合至圆心
     */
    function restorePop() {
        popupOverlayCloser.click();
        _oldPopFeature && threadsQueue.add(dealOutAnimateFeature);
    }

    /**
     * 显示overlay弹窗信息
     * @param {feature} fea 
     */
    function overlayShowPop(fea) {
        let coordinate = fea.get("center");
        let position = [...coordinate];
        position[1] = Number(position[1]) + mapView.getResolution() * 41;
        let htmlmetadata = getPopHtmlByfeature(fea);
        content.innerHTML = htmlmetadata["html"];
        htmlmetadata["width"] && $(content).css("width", htmlmetadata["width"] + "px");
        htmlmetadata["height"] && $(content).css("height", htmlmetadata["height"] + "px");
        popupOverlay.setPosition(position);
    }

    getPopHtmlByfeature = function(fea) {
        let popSpanhtml = '';
        let divWidth = 0;
        initCST.popOvelayShowFields.forEach(field => {
            let text = fea.get(field);
            if (text) {
                let spanText = field + "：" + text;
                popSpanhtml += "<span>" + spanText + "</span>";
                let widthNow = spanText.length * 14;
                widthNow > divWidth && (divWidth = widthNow);
            }
        })
        return {
            html: "<div>" + popSpanhtml + "</div>",
            width: divWidth,
            // height: 200
        };
    }


    /**
     * 按半径扩散至圆周
     * @param {feature} fea 圆心位置的feature
     */
    function dealInAnimateFeature(fea) {
        if(!fea) return threadsQueue.execute();
        singleLableLayerSource.addFeature(fea);
        addfeatureByfeature(fea);
        singlePopLableLayer.set("direction", 'in');
        singlePopLableLayer.setOpacity(0);
        animateLine.initAndStart(singleLableLayer, singlePopLableLayer ,function () {
            singlePopLableLayer.setOpacity(1);
            threadsQueue.execute();
        });
        _oldPopFeature = fea;
        currentlabelLayer.changed();
    }

    /**
     * 按半径从圆周聚合至圆心
     * @param {feature} fea 用于判断函数执行来源
     */
    function dealOutAnimateFeature() {
        if (!_oldPopFeature) return threadsQueue.execute();
        singleLableLayerSource.clear();
        singlePopLableLayerSource.clear();
        singleLableLayerSource.addFeature(_oldPopFeature);
        addfeatureByfeature(_oldPopFeature)
        singlePopLableLayer.set("direction", 'out');
        singlePopLableLayer.setOpacity(0);
        animateLine.initAndStart(singlePopLableLayer, singleLableLayer, function () {
            singleLableLayerSource.clear();
            singlePopLableLayerSource.clear();
            _oldPopFeature = null;
            currentlabelLayer.changed();
            threadsQueue.execute();
        });
    }

    /**
     * 为动画准备数据，生成feature并添加至singlePopLableLayer层
     * @param {feature} centerFeature 
     */
    function addfeatureByfeature(centerFeature) {
        let children = getzqData.getdataByParentCode(centerFeature.get("code"));
        let pointOffset = getPopPoint(children.length, initCST.scatteringRadius);
        let feaPixel = olmap.getPixelFromCoordinate(centerFeature.get("center"));
        children.forEach((item, index) => {
            item["isMark"] = true;
            item["center"] = olmap.getCoordinateFromPixel([feaPixel[0] + pointOffset[index][1], feaPixel[1] + pointOffset[index][0]]);
            singlePopLableLayerSource.addFeature(createFeature(item));
        })
    }

    /**
     * 序列化动画事件
     */
    function setLabels() {
        let zoom = mapView.getZoom();
        Object.keys(initCST.zoomMapping).forEach(item => {
            if (zoom >= initCST.zoomMapping[item][0] && zoom < initCST.zoomMapping[item][1]) {
                _zqLevelBefore = _zqLevelNow;
                _zqLevelNow = parseInt(item);
            }
        })
        threadsQueue.add(creatAnimateThread(zoom, mapView.calculateExtent(olmap.getSize())));
    }

    /**
     * 根据真实位置生成动画
     * @param {number} zoom 地图当前级别
     * @param {Array} extent 地图当前视角的范围
     * @returns {Function} function
     */
    function creatAnimateThread(zoom, extent) {
        return function () {
            let dataNow = getzqData.getdataByLevel(zoom, extent);
            if(_zqLevelBefore !== _zqLevelNow){
                nextlabelLayer.set("direction", _ZoomBefore < zoom ? 'in' : 'out');
                _ZoomBefore = zoom;
                nextlabelLayer.setOpacity(0);
                nextlabelLayerSource.addFeatures(getFeatures(dataNow.datas));
                animateLine.initAndStart(currentlabelLayer, nextlabelLayer, function () {
                    changeLayer();
                    threadsQueue.execute();
                });
            }else{
                nextlabelLayerSource.addFeatures(getFeatures(dataNow.datas));
                changeLayer();
                threadsQueue.execute();
            }
        }
    }

    /**
     * 根据数据生成feature
     * @param {Array} data 
     * @returns {Array} features
     */
    function getFeatures(data) {
        let feas = [];
        if (data.length) {
            data.forEach(element => {
                feas.push(createFeature(element));
            });
        }
        return feas;
    }

    function createFeature(setting) {
        let iconFeature = new ol.Feature(new ol.geom.Point(setting["center"]));
        setting["extent"] && iconFeature.set("nextlevelextent", setting["extent"]);
        iconFeature.set("nextlevelcenter", setting["center"]);
        iconFeature.set("id", setting["code"]);
        if (setting["type"] === "scatter") {
            iconFeature.set("isMark", true);
        }
        Object.keys(setting).forEach(field => {
            iconFeature.set(field, setting[field]);
        })
        return iconFeature;
    }

    function createlayerStyle() {
        return function (fea) {
            return getFeatureStyle(fea);
        }
    }

    /**
     * 根据feature返回相应样式
     * @param {Feature} fea require
     * @param {Number} iconOpacity require
     * 
     * @returns {Style}
     */
    function getFeatureStyle(fea, animateOpacity) {
        if (!fea) return;
        let geometry = fea.getGeometry();
        let isMark = fea.get("isMark");
        if (geometry instanceof ol.geom.Point) {
            if (typeof animateOpacity === "undefined") {
                animateOpacity = 1;
            }
            return isMark ? getIconStyle(animateOpacity) : getCircleStyle(fea, animateOpacity);
        }
    }

    /**
     * 获取icon样式
     * @param {number} animateOpacity 动画生成过程中的透明度
     * @returns {style} 
     */
    function getIconStyle(animateOpacity) {
        return new ol.style.Style({
            image: new ol.style.Icon({
                anchor: [0.28, 0.98],
                crossOrigin: 'anonymous',
                src: initCST.PopIconUrl,
                opacity: animateOpacity
            })
        })
    }

    /**
     * 获取圆型样式
     * @param {feature} fea 当前feature
     * @param {number} animateOpacity 动画生成过程中的透明度
     * @returns {style}
     */
    function getCircleStyle(fea, animateOpacity) {
        let rgba = getRgbaByFeatureAndOpacity(fea, animateOpacity)
        let text = getTextByfeature(fea) + "";
        return new ol.style.Style({
            image: new ol.style.Circle({
                radius: 15,
                stroke: new ol.style.Stroke({
                    color: rgba["stroke"],
                    width:9
                }),
                fill: new ol.style.Fill({
                    color: rgba["fill"]
                }),
            }),
            text: new ol.style.Text({
                font: '12px sans-serif',
                text: text,
                offsetY: 4,
                fill: new ol.style.Fill({
                    color: rgba["text"]
                }),
            })
        });
    }

    /**
     * 获取与feature对应的rgb色值
     * @param {feature} fea 当前feature
     * @param {number} animateOpacity 动画生成过程中的透明度
     * @returns {Object} rgb
     */
    function getRgbaByFeatureAndOpacity(fea, animateOpacity) {
        let opacity = {stroke: 0.6, fill: 1};
        let value = fea.get(initCST.dataField);
        let MaxValue = fea.get("maxvalue");
        let MinValue = fea.get("minvalue");
        if (_oldPopFeature && fea.get("id") === _oldPopFeature.get("id")) {
            opacity.stroke = 0.1;
            opacity.fill = 0.2;
        }
        let rgb = getRgb(value, MaxValue, MinValue);
        return {
            stroke: `rgba(${rgb["stroke"]}, ${opacity.stroke * animateOpacity})`,
            fill: `rgba(${rgb["fill"]}, ${opacity.fill * animateOpacity})`,
            text: `rgba(16, 19, 26, ${opacity.fill * animateOpacity})`
        }
    }

    /**
     * rgba色值处理回调
     */
    getRgb = function (value, maxValue, minValue) {
        let rate = value / maxValue;
        return {
            stroke: `255, ${255 - parseInt(rate * 255)}, 0`,
            fill: `255, ${255 - parseInt(rate * 255)}, 0`
        }
    }

    /**
     * showField的简化方法
     */
    function getTextByfeature(fea) {
        let text = (fea.get(initCST.showField) || '') + '';
        switch (text.length) {
            case 5:
                text = text.slice(0, 1) + "万+";
                break;
            case 6:
                text = text.slice(0, 2) + "万+";
                break;
            case 7:
                text = text.slice(0, 3) + "万+";
                break;
            case 8:
                text = text.slice(0, 4) + "万+";
                break;
        
            default:
                break;
        }
        return text;
    }

    /**
     * 初始化功能使用的图层
     */
    function initLayer() {
        popupOverlay = new ol.Overlay({
            element: container
        });
        olmap.addOverlay(popupOverlay);
        $(container).show();
        singleLableLayer = getLayerByZAndSource(160, singleLableLayerSource);
        singlePopLableLayer = getLayerByZAndSource(161, singlePopLableLayerSource);
        currentlabelLayer = getLayerByZAndSource(156, currentlabelLayerSource);
        nextlabelLayer = getLayerByZAndSource(157, nextlabelLayerSource);
        map.addLayer("ZqPolymerization_singleLable_Layer", singleLableLayer);
        map.addLayer("ZqPolymerization_singlePopLable_Layer", singlePopLableLayer);
        map.addLayer("ZqPolymerization_current_label_Layer", currentlabelLayer);
        map.addLayer("ZqPolymerization_next_label_Layer", nextlabelLayer);
    }

    // 初始化UI
    function initUi() {
        $("body").append(popHtml);
        container = document.getElementById('popup_ZqPolymerization');
        content = document.getElementById('popup_ZqPolymerization-content');
        popupOverlayCloser = document.getElementById('popup_ZqPolymerization-closer');
    }

    /**
     * 每次动画结束（不包括按圆周相关的动画）后，应当处理当前的Layer与source，为下一次动画做准备，
     * 因为每次动画都应该是以currentlabelLayer中的feature为动画起点
     */
    function changeLayer() {
        map.removeLayer("ZqPolymerization_current_label_Layer");
        map.removeLayer("ZqPolymerization_next_label_Layer");
        currentlabelLayerSource = nextlabelLayerSource;
        nextlabelLayerSource = new ol.source.Vector();
        currentlabelLayer = getLayerByZAndSource(156, currentlabelLayerSource);
        nextlabelLayer = getLayerByZAndSource(157, nextlabelLayerSource);
        map.addLayer("ZqPolymerization_current_label_Layer", currentlabelLayer);
        map.addLayer("ZqPolymerization_next_label_Layer", nextlabelLayer);
    }

    function getLayerByZAndSource(zindex, source){
        return new ol.layer.Vector({
            style: createlayerStyle(),
            source: source,
            zIndex: zindex,
        })
    }

    /**
     * 获取圆周位置的偏移量
     * @param {Number} total 个数
     * @param {number} radius 半径
     * @returns {Array} offsetArr 偏移量数组
     */
    function getPopPoint(total, radius) {
        if (total < 3) {
            total = 3;
        }
        let offsetArr = [];
        let deg = 360 / total;
        // 如果想要旋转园，改变currentDeg的初始值即可
        for (let currentDeg = 0; currentDeg < 360; currentDeg+=deg) {
            let radian = (Math.PI / 180) * currentDeg;
            offsetArr.push([radius * Math.cos(radian), radius * Math.sin(radian)]);
        }
        return offsetArr;
    }

    function setVisible(isshow) {
        if (isinit) {
            currentlabelLayer.setVisible(isshow);
            nextlabelLayer.setVisible(isshow);
            isUsing = isshow;
            if (isshow) {
                setLabels();
            }
        }
    }

    function destory() {
        currentlabelLayerSource.clear();
        nextlabelLayerSource.clear();
        olmap.removeOverlay(popupOverlay);
        map.removeLayer("ZqPolymerization_singleLable_Layer");
        map.removeLayer("ZqPolymerization_singlePopLable_Layer");
        map.removeLayer("ZqPolymerization_next_label_Layer");
        map.removeLayer("ZqPolymerization_current_label_Layer");
        olmap.un('movestart', movestartEvevt);
        olmap.un('moveend', moveendEvevt);
        olmap.un("pointermove", changeCursor);
        olmap.un("click", mapClickEvent);
        isinit = false;
    }

    function clear() {
        currentlabelLayerSource.clear();
        nextlabelLayerSource.clear();
        popupOverlayCloser.click();
    }

    return {
        init: init,
        destory: destory,
        clear: clear,
        setVisible: setVisible
    }
});